package tech.summerly.weather.component.fragments

import android.arch.lifecycle.Lifecycle
import android.arch.lifecycle.LifecycleObserver
import android.arch.lifecycle.OnLifecycleEvent
import android.graphics.*
import android.os.Bundle
import android.support.constraint.ConstraintSet
import android.support.transition.ChangeBounds
import android.support.transition.TransitionManager
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.amap.api.maps2d.AMapOptions
import com.amap.api.maps2d.CameraUpdateFactory
import com.amap.api.maps2d.MapView
import com.amap.api.maps2d.model.BitmapDescriptorFactory
import com.amap.api.maps2d.model.LatLngBounds
import com.amap.api.maps2d.model.Marker
import com.amap.api.maps2d.model.MarkerOptions
import com.google.android.exoplayer2.ExoPlayerFactory
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import kotlinx.android.synthetic.main.fragment_live_weather.*
import kotlinx.android.synthetic.main.fragment_live_weather.view.*
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.launch
import tech.summerly.weather.AppContext
import tech.summerly.weather.R
import tech.summerly.weather.component.adapter.CameraDescriptionAdapter
import tech.summerly.weather.data.LiveStreamRepository
import tech.summerly.weather.data.WeatherRepository
import tech.summerly.weather.model.CameraMapConfiguration
import tech.summerly.weather.model.LiveWeatherSource
import tech.summerly.weather.model.Region
import tech.summerly.weather.util.*

class LiveWeatherFragment : Fragment() {

    companion object {
        const val TAG = "LiveWeatherFragment"

        fun newInstance(region: Region): LiveWeatherFragment {
            val bundle = Bundle()
            bundle.putParcelable("region", region)
            val fragment = LiveWeatherFragment()
            fragment.arguments = bundle
            return fragment
        }
    }

    //当前直播的区域
    private val region: Region by arguments

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_live_weather, container, false)
    }

    private val markers = HashMap<String, Marker>()

    private lateinit var cameraDescriptionAdapter: CameraDescriptionAdapter
    /**
     * 当前正在播放的摄像头
     */
    private lateinit var currentCamera: LiveWeatherSource

    private val keyFrameHideSummary by lazy { ConstraintSet().also { it.clone(context, R.layout.fragment_live_weather_out) } }

    private val keyFrameNormal by lazy { ConstraintSet().also { it.clone(context, R.layout.fragment_live_weather) } }

    private var isHideSummary = false

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) = with(view) {
        if (!LiveStreamRepository.isRegionSupport(region)) {
            toast(string(R.string.error_live_do_not_supported))
            closeSelf()
            return@with
        }

        currentCamera = LiveStreamRepository.getDefaultLive(region)
        mapView.observeLifecycle(lifecycle)
        toolbar.setNavigationOnClickListener {
            closeSelf()
        }
        lifecycle.addObserver(exoLifecycleObserver)
        val availableCameras = LiveStreamRepository.getTotalAvailableLive(region)
        initMapView(mapView,
                LiveStreamRepository.getCameraMapConfiguration(region),
                availableCameras)
        //初始化文字摄像头列表
        cameraDescriptionAdapter = CameraDescriptionAdapter(availableCameras) { _, position ->
            switchLiveSource(availableCameras[position])
        }
        recyclerCameras.adapter = cameraDescriptionAdapter

        container.setOnClickListener {
            TransitionManager.beginDelayedTransition(container, ChangeBounds())
            if (isHideSummary) {
                keyFrameNormal.applyTo(container)
            } else {
                keyFrameHideSummary.applyTo(container)
            }
            isHideSummary = !isHideSummary
        }
        setData()
        //切换到当前摄像头
        switchLiveSource(currentCamera, true)
        Unit
    }

    private fun setData() = launch(UI) {
        try {
            //显示实时天气
            val weather = WeatherRepository.getRealtimeWeather(region)
            val wind = weather.wind
            textSky.text = "%s %s,%s".format(weather.getSkyConString(), wind.getWindDirection(), wind.getWindName())
            val local = weather.precipitation["local"].asJsonObject
            textPrecipitation.text = "降水强度: %s".format(local["intensity"].asString)
        } catch (e: Exception) {

        }
    }

    private fun initMapView(mapView: MapView,
                            configuration: CameraMapConfiguration,
                            availableCameras: List<LiveWeatherSource>) {
        val map = mapView.map
        map.moveCamera(CameraUpdateFactory
                .newLatLngBounds(
                        LatLngBounds(configuration.southwest.toLatLng(),
                                configuration.northeast.toLatLng()), 0))
        markers.clear()
        availableCameras.forEach {
            val marker = map.addMarker(MarkerOptions()
                    .position(it.position.toLatLng())
                    .icon(BitmapDescriptorFactory.fromBitmap(imageCameraNormal))
                    .draggable(false))
            marker.`object` = it
            markers[it.id] = marker
        }
        //禁止一些手势
        map.uiSettings.apply {
            setAllGesturesEnabled(false)
            setZoomInByScreenCenter(false)
            setMenuVisibility(false)
            setHasOptionsMenu(false)
            isMyLocationButtonEnabled = false
            isZoomControlsEnabled = false
            logoPosition = AMapOptions.LOGO_POSITION_BOTTOM_RIGHT
        }
        map.setOnMarkerClickListener {
            val source = it.`object` as? LiveWeatherSource
            if (source != null) {
                switchLiveSource(source)
                true
            } else {
                false
            }
        }
    }

    private val imageCameraNormal: Bitmap by lazy {
        BitmapFactory.decodeResource(resources, R.drawable.i_camera)
    }

    private val imageCameraPlaying: Bitmap by lazy {
        //tint a assent color for CameraNormal
        val paint = Paint()
        paint.setColorFilter(PorterDuffColorFilter(color(R.color.color_secondary), PorterDuff.Mode.SRC_IN))
        val new = Bitmap.createBitmap(imageCameraNormal.width, imageCameraNormal.height, Bitmap.Config.ARGB_8888)
        Canvas(new).drawBitmap(imageCameraNormal, 0f, 0f, paint)
        new
    }


    //切换播放源
    private fun switchLiveSource(source: LiveWeatherSource, force: Boolean = false) {
        if (currentCamera == source && !force) {
            return
        }
        //更新toolbar title
        view?.toolbar?.title = source.name
        //改变文字列表的选择
        cameraDescriptionAdapter.setSelected(source.id)
        //改变marker的icon
        markers[currentCamera.id]?.setIcon(BitmapDescriptorFactory.fromBitmap(imageCameraNormal))
        markers[source.id]?.setIcon(BitmapDescriptorFactory.fromBitmap(imageCameraPlaying))

        currentCamera = source
        view?.playerViewEmbedded?.player = getPlayer()
        exoLifecycleObserver.source = source.mediaSource
        log { "try to play $source" }
        getPlayer().prepare(source.mediaSource)
        getPlayer().playWhenReady = true
    }

    private var player: SimpleExoPlayer? = null

    private fun getPlayer(): SimpleExoPlayer {
        return player ?: createExoPlayer().also { player = it }
    }

    private fun createExoPlayer(): SimpleExoPlayer {
        val instance = ExoPlayerFactory.newSimpleInstance(AppContext.instance, DefaultTrackSelector())
        //无限循环且静音
        instance.repeatMode = Player.REPEAT_MODE_ONE
        instance.volume = 0f
        return instance
    }

    private val exoLifecycleObserver = object : LifecycleObserver {

        //资源缓存
        var source: MediaSource? = null

        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        fun startPlay() {
            source?.let {
                getPlayer().prepare(it)
                getPlayer().playWhenReady = true
            }
        }


        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        fun releaseExo() {
            player?.release()
            player = null
        }

    }
}


